
package com.myutil.qiniu;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.lang3.StringUtils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.myutil.utils.ConfigFileUtils;
import com.myutil.utils.email.EmailUtil;
import com.qiniu.common.QiniuException;
import com.qiniu.util.Auth;

public class QiNiuSSLCertService {
	
	private SSLManager sslManager;
	
	public QiNiuSSLCertService(String qiniu_accessKey ,String qiniu_secretKey){
		/*this.qiniu_accessKey = qiniu_accessKey;
		this.qiniu_secretKey = qiniu_secretKey;*/
		
		  //密钥配置
        Auth auth = Auth.create(qiniu_accessKey, qiniu_secretKey);
        //实例化一个BucketManager对象
        this.sslManager = new SSLManager(auth);
	}
	
	public SSLManager getSSLManager( ) {
		return this.sslManager;
	}
	

	public void sendExpriedCertEmailNotify(JSONObject config ) {
		System.out.println("检查过期的证书并发送邮件通知...");
		
		
		//要监控的证书
		List<String> certNames = new ArrayList<>();
		JSONArray updateList = config.getJSONObject("qiniu").getJSONArray("updateList");
		for (int i = 0; i < updateList.size(); i++) {
			String certName = updateList.getJSONObject(i).getString("sslCertName");
			certNames.add(certName);
		}
		
		JSONObject notify = config.getJSONObject("notify");

		JSONArray list = listExpriedCertList();
		String subject = "证书快还有"+ConfigFileUtils.EMAIL_SEND_EXPIRE_NOTIFY_BEFORE_DAY+"天过期或者已经过期 提醒";
		String html ="";
		if(list!=null && !list.isEmpty()) {
			
			for (int i = 0; i < list.size(); i++) {
				JSONObject cert = list.getJSONObject(i);
				String certCommonName = cert.getString("common_name");// 证书通用名称 *.xiaoyung.com
				if(certNames.contains(certCommonName)) {
					String beginDateStr = SSLManager.formatSecondTimestamp(cert.getLong("not_before"));
					String endDateStr = SSLManager.formatSecondTimestamp(cert.getLong("not_after"));
					html+="<h1>证书:"+ certCommonName+ " 有效时间:"+beginDateStr+" 至 "+endDateStr+"</h1><br/>";
				}
			}
		}
		if(!StringUtils.isEmpty(html)) {
			System.out.println("发现快过期"+ConfigFileUtils.EMAIL_SEND_EXPIRE_NOTIFY_BEFORE_DAY+"或者已过期证书:"+html);
			EmailUtil.sendEmail(subject, html, notify);
		}else {
			System.out.println("没有发现快过期"+ConfigFileUtils.EMAIL_SEND_EXPIRE_NOTIFY_BEFORE_DAY+"天或者已过期证书");
		}
	}
	
	//查看过期或者快过期的证书 5天为标准
	public JSONArray listExpriedCertList() {
		JSONArray expriedList = new JSONArray();
		// 查看最新证书
		JSONArray certsList = sslManager.getSSLCertList();
		for (int i = 0; i < certsList.size(); i++) {
			JSONObject cert = certsList.getJSONObject(i);
			Date endDate = new Date(cert.getLong("not_after") * 1000);// 过期时间
			Date endDateDiff10day = new Date(
					endDate.getTime() - 3600 * 1000 * 24 * ConfigFileUtils.EMAIL_SEND_EXPIRE_NOTIFY_BEFORE_DAY);

			String certCommonName = cert.getString("common_name");// 证书通用名称

			if (endDateDiff10day.getTime() < new Date().getTime()) {
				// 重新查询最新的证书
				cert = sslManager.getLatestSSLCertByCertName(certCommonName);
			}

			endDate = new Date(cert.getLong("not_after") * 1000);// 过期时间
			endDateDiff10day = new Date(
					endDate.getTime() - 3600 * 1000 * 24 * ConfigFileUtils.EMAIL_SEND_EXPIRE_NOTIFY_BEFORE_DAY);
			if (endDateDiff10day.getTime() < new Date().getTime()) {
				// 快过期了
				expriedList.add(cert);
			}

		}
		return expriedList;
	}
	
	
	//{"code":0.0,"marker":"100","error":"","certs":[{"certid":"66ebdb11ce27951dbff8bd34","name":"*.xiaoyung.com","uid":1.381540581E9,"common_name":"*.xiaoyung.com","dnsnames":["*.xiaoyung.com"],"create_time":1.726733073E9,"not_before":1.7222112E9,"not_after":1.730073599E9,"orderid":"","product_short_name":"","product_type":"single_wildcard","cert_type":"DV","encrypt":"ECDSA","encryptParameter":"","enable":false,"child_order_id":"","state":"","auto_renew":false,"renewable":false},{"certid":"5c25e9efb38b3871bb0000f2","name":"wxtest1.xiaoyung.com","uid":1.381540581E9,"common_name":"wxtest1.xiaoyung.com","dnsnames":["wxtest1.xiaoyung.com"],"create_time":1.545988591E9,"not_before":1.5459552E9,"not_after":1.5775344E9,"orderid":"5c25dd5554be51503d0003ee","product_short_name":"TrustAsiaTLSC1","product_type":"single","cert_type":"DV","encrypt":"RSA","encryptParameter":"2048","enable":false,"child_order_id":"","state":"","auto_renew":false,"renewable":false},{"certid":"5bfe6b033e543d10550000a3","name":"公有空间域名","uid":1.381540581E9,"common_name":"upload2.xiaoyung.com","dnsnames":["upload2.xiaoyung.com"],"create_time":1.543400195E9,"not_before":1.5433632E9,"not_after":1.5749424E9,"orderid":"5bfe4a65340597622b000586","product_short_name":"TrustAsiaTLSC1","product_type":"single","cert_type":"DV","encrypt":"RSA","encryptParameter":"2048","enable":false,"child_order_id":"","state":"","auto_renew":false,"renewable":false},{"certid":"5bfe6b03340597622b00059e","name":"私有空间域名","uid":1.381540581E9,"common_name":"upload1.xiaoyung.com","dnsnames":["upload1.xiaoyung.com"],"create_time":1.543400195E9,"not_before":1.5433632E9,"not_after":1.5749424E9,"orderid":"5bfe4aec54be5171ca000563","product_short_name":"TrustAsiaTLSC1","product_type":"single","cert_type":"DV","encrypt":"RSA","encryptParameter":"2048","enable":false,"child_order_id":"","state":"","auto_renew":false,"renewable":false}]}
	public void updateSSLCert(String[] domainNames,String sslCertName,String sslCertPath,String sslPrivatekeyPath,Boolean deleteOldCert) {
		//查看最新证书
		JSONObject latestCert = sslManager.getLatestSSLCertByCertName(sslCertName);
		Date endDate = new Date(latestCert.getLong("not_after") * 1000);//过期时间
		Date endDateDiff10day = new Date(endDate.getTime()-3600*1000*24* ConfigFileUtils.BEFORE_DAY);
		
		String newCertId = null;
		if( endDateDiff10day.getTime() < new Date().getTime() ) {
			//已经过期 或者 还有10天过期 就上传更新证书
			
			String pri = ConfigFileUtils.readFileToString(sslPrivatekeyPath);
			String ca = ConfigFileUtils.readFileToString(sslCertPath) ;
			
			newCertId = sslManager.uploadSSLCert(sslCertName,sslCertName,pri,ca);
			
			System.out.println("上传证书成功 certId:"+newCertId);
			/*JSONObject cert = bucketManager.getSSLCert(certId);
			System.out.println("====cert===:");
			System.out.println(cert);*/
			
			for (int i = 0; i < domainNames.length; i++) {
				String domainName = domainNames[i];
				sslManager.domainHttpsConf(domainName, newCertId,false,false);
				System.out.println("域名"+domainName+" https证书设置成功");
			}
			
			//重新查询最新的证书
			latestCert = sslManager.getLatestSSLCertByCertName(sslCertName);
		}else {
			System.out.println("没有快过期的证书"+sslCertName+" 不需要重新上传;  最新的证书:"+latestCert);
		}
		
		if(deleteOldCert) {//上传了新证书
			//删除旧证书
			JSONArray certList = sslManager.getSSLCertList();
			for (int i = 0; i < certList .size(); i++) {
				JSONObject oldCert = certList .getJSONObject(i);
				String certid = oldCert.getString("certid");
				String certRemarkName = oldCert.getString("name");//证书备注名称
				String certCommonName = oldCert.getString("common_name");//证书通用名称
				//Date certCreateTime = cert.getDate("create_time");//创建时间
				if(certCommonName.equals(sslCertName) && !certid.equals(latestCert.getString("certid"))) {
					System.out.println("删除旧证书: 证书通用名称: "+certCommonName+" 证书备注名称: "+certRemarkName+" 证书id: "+certid);
					try {
						JSONObject deleteSSLRet = sslManager.deleteSSLCert(certid);
						System.out.println("删除旧证书 成功 result:"+deleteSSLRet);	
					}catch(Exception ex) {
						String msg = ex.getMessage();
						if(ex.getCause() instanceof QiniuException) {
							QiniuException qiniuEx = (QiniuException) (ex.getCause());
							msg = "code: "+qiniuEx.code()+" error: "+ qiniuEx.error();
						}
						System.out.println("删除旧证书 失败:"+msg);
					}
					
				}
			}
		}
	}
	
	public static void main(String[] args) {
		//java -jar update-cert.jar -f /data/ssl/update-cert.conf
		
		// 定义阶段
		Options options = new Options();

		Option filePathOption = new Option("f", true, "配置文件路径");
		filePathOption.setRequired(false); // 文件路径为必传选项
		filePathOption.setArgName("configFilePath");
		//Option deleteOldOption = new Option("d", false, "删除旧证书");
		Option helpOption = new Option("h", "help", false, "帮助文档");

		options.addOption(filePathOption);
		//options.addOption(daemonRunOption);
		options.addOption(helpOption);

		// 解析阶段
		CommandLineParser parser = new DefaultParser();
		CommandLine cmd;
		try {
			cmd = parser.parse(options, args);
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
		
		// 获取文件路径
		if (cmd.hasOption(filePathOption)) {
			String filePath = cmd.getOptionValue(filePathOption);
			System.out.println("配置文件路径 : " + filePath);
			JSONObject config = ConfigFileUtils.readFileToJson(filePath);
			
			
			String accessKey = config.getString("accessKey");
			String secretKey = config.getString("secretKey");
			
			/*if(cmd.hasOption(deleteOldOption)) {
				
			}else {*/
				JSONArray updateList = config.getJSONArray("updateList");
				for (int i = 0; i < updateList.size(); i++) {
					JSONObject update=updateList.getJSONObject(i);
					
					Boolean deleteOldCert = update.getBoolean("deleteOldCert");
					if (deleteOldCert == null) {
						deleteOldCert = false;
					}
					String sslCertName = update.getString("sslCertName");
					String sslCertPath = update.getString("sslCertPath");
					String sslPrivatekeyPath = update.getString("sslPrivatekeyPath");
					
					String[] domainNames = update.getString("domainNames").split(",");
					
					QiNiuSSLCertService qiNiuUtil = new QiNiuSSLCertService(accessKey,secretKey);
					qiNiuUtil.updateSSLCert(domainNames,sslCertName,sslCertPath,sslPrivatekeyPath,deleteOldCert);
				}
			//}
			
			
			
		}else {
			//if (args.length == 0 || cmd.hasOption(helpOption)) {
				HelpFormatter formatter = new HelpFormatter();
				formatter.printHelp("java -jar update-cert.jar -f /data/ssl/update-cert.conf", options);
			//}
		}

		// 后台运行
		/*if (cmd.hasOption(daemonRunOption)) {
			System.out.println("后台运行");
		}*/
		
		
	}

}
